#pragma once

#include <infiniband/verbs.h>

#include <string>
#include <vector>

#include "flatbuffers/flatbuffers.h"

//! RDMA协议
#include "allocate_response_generated.h"    // RDMA分配先用(Rkey和远程地址)
#include "meta_request_generated.h"         // RDMA读写请求元数据


//! TCP协议
#include "delete_keys_generated.h"          // 根据健删除KV Cache
#include "get_match_last_index_generated.h" // TODO: 什么含义？
#include "tcp_payload_request_generated.h"  // TCP请求元数据

using namespace flatbuffers;


//! 最大Post Send WR数
#define MAX_SEND_WR 8192


//! 最大Post Recv WR数
#define MAX_RECV_WR 128


//! 最大单项RDMA操作WR数
#define MAX_RDMA_OPS_WR 8000



//! 每MAX_WR_BATCH个RDMA WRITE请求共享一个RDMA_SIGNAL
#define MAX_WR_BATCH 32

#define MAGIC 0xdeadbeef      // 数据校验特殊标记
#define MAGIC_SIZE 4

#define OP_RDMA_EXCHANGE      'E'
#define OP_RDMA_READ          'A'
#define OP_RDMA_WRITE         'W'
#define OP_CHECK_EXIST        'C'
#define OP_GET_MATCH_LAST_IDX 'M'
#define OP_DELETE_KEYS        'X'
#define OP_SIZE                1

#define OP_TCP_PUT            'P'
#define OP_TCP_GET            'G'
#define OP_TCP_PAYLOAD        'L'


/**
 *! @brief  根据opcode返回具体的操作名称
 * 
 * @param opcode 操作代码 
 * @return std::string  操作名称
 */
std::string op_name(char opcode);




//! 定义常见错误码
#define INVALID_REQ    400
#define FINISH         200
#define TASK_ACCEPTED  202
#define INTERNAL_ERROR 500
#define KEY_NOT_FOUND  404
#define RETRY          408
#define SYSTEM_ERROR   503
#define OUT_OF_MEMORY  507

#define RETURN_CODE_SIZE sizeof(int)

#define PROTOCOL_BUFFER_SIZE (4 << 20)  // 4M could be enough


//! 自定协议头
// 便于网络传输后解析使用__attribute__((packed))
typedef struct __attribute__((packed)) {
    unsigned int magic;
    char op;
    unsigned int body_size;
} header_t;




//! RDMA连接信息
typedef struct __attribute__((packed)) rdma_conn_info_t {
    uint32_t qpn;        // QP 编号
    uint32_t psn;        // 包序列号
    union ibv_gid gid;   // RoCE v2
    uint16_t lid;        // IB, RoCE场景下无效
    uint32_t mtu;        // 单个数据包的大小(通信的两个QP必须设置已知)
} rdma_conn_info_t;


#define FIXED_HEADER_SIZE sizeof(header_t)




/**
 *! @brief 固定大小内存空间分配器
 */
class FixedAllocator : public Allocator {
public:
    FixedAllocator(void* buffer, size_t size) 
        : buffer_(buffer), size_(size), offset_(0) {}

    /**
     *! @brief 分别指定大小的内存空间并返回地址指针
     * 
     * @param size 待分配的大小
     * @return uint8_t*  分配的内存地址
     */
    uint8_t* allocate(size_t size)   override;



    /**
     *! @brief 释放内存特定大小空间
     * 
     * @param buffer 内存地址
     * @param size   待释放的大小
     */
    void     deallocate(uint8_t* buffer, size_t size) override;


private:
    void*  buffer_;    // 内存数据地址指针
    size_t size_;      // 内存数据大小
    size_t offset_;    // 内存数据偏移
};
